-- DungeonTaskM
-- Created by chengb Oct/31/2015
-- 迷宫中任务

module("DungeonTaskM", package.seeall);

-- 模块名称
local PURE_FILE = "DungeonTaskM";

-- 迷宫中任务配置表
local taskTable = {};

-- 根据完成规则存放任务
local taskByRule = {};

-- 根据领取规则存放任务
local taskByAssignRule = {};

-- 所有子规则
local rules = {};

-- 内部函数声明
local whenLeaveDungeon;

-- 载入配置表
local _init = false;
local loadCsv = function()
    if _init then return end
    _init = true;

    taskTable = {};
    taskByRule = {};
    taskByAssignRule = {};

    -- 转换配置表
    local dungeon_task_CSV = get_dungeon_task_CSV();
    for i = 1, #dungeon_task_CSV do
        local id = dungeon_task_CSV[i].id;
        taskTable[id] = dungeon_task_CSV[i];

        -- 根据完成规则存放
        local rule = dungeon_task_CSV[i].rule;
        if type(taskByRule[rule]) ~= 'table' then
            taskByRule[rule] = {};
        end
        table.insert(taskByRule[rule], dungeon_task_CSV[i]);

        local assignRule = dungeon_task_CSV[i].assign_rule;
        if type(taskByAssignRule[assignRule]) ~= 'table' then
            taskByAssignRule[assignRule] = {};
        end
        table.insert(taskByAssignRule[assignRule], dungeon_task_CSV[i]);
    end
    dungeon_task_CSV = {};
end

-- 初始化
function init()
    loadCsv();

    -- 关注玩家离开迷宫的事件
    EventMgr.removeAll(PURE_FILE);
    EventMgr.register(PURE_FILE, event.LEAVE_DUNGEON, whenLeaveDungeon);

    -- 载入所有的规则处理子模块
    rules = LOAD_PATH("game/logic/module/dungeon_tasks");
end

-- 检索任务配置
function query(taskId, path)
    local m = taskTable[taskId];

    if not m or path == "" or not path then
        return m;
    end

    return m[path];
end

-- 根据完成规则获取任务
function getTasksByRule(rule)
    return taskByRule[rule];
end

-- 根据领取规则获取任务
function getTasksByAssignRule(assignRule)
    return taskByAssignRule[assignRule];
end

-- 玩家离开迷宫的事件回调
whenLeaveDungeon = function(args)
    -- 清除所有迷宫中任务
    if ME.user.dbase:query("dungeon_tasks") ~= nil then
        trace(PURE_FILE, "玩家离开迷宫，清除所有迷宫中任务。");
        ME.user.dbase:delete("dungeon_tasks");
    end
end

-- 领取一个任务
function assignTask(taskId, para, times)
    assert(type(taskId) == "number", "taskId 必须为整型");
    assert(type(para)   == "table",  "para 必须为table类型");
    assert(type(times)  == "number", "times 必须为整型");

    if not DungeonM.isInDungeon() then
        trace(PURE_FILE, "玩家不在迷宫中，无法领取迷宫中任务。");
        return false;
    end

    if type(query(taskId)) ~= 'table' then
        trace(PURE_FILE, "任务(%d)不存在，无法领取。", taskId);
        return false;
    end

    DungeonLogM.addLog(string.format("[DungeonTaskM]领取任务(%d), times = %d",
        taskId, times));

    local tasks = ME.user.dbase:query("dungeon_tasks", {});
    if tasks[taskId] then
        -- 已经有该任务了，直接累积次数
        tasks[taskId]["times"] = tasks[taskId]["times"] or 0;
        tasks[taskId]["times"] = tasks[taskId]["times"] + times;
        return true;
    end

    -- 初始化进度和可完成次数
    tasks[taskId] = {
        ["progress"] = 0,
        ["times"]    = times,
    };

    tasks[taskId] = table.add(tasks[taskId], para);
    ME.user.dbase:set("dungeon_tasks", tasks);

    return true;
end

-- 尝试完成任务
function tryComplete(taskId, count)
    local config = query(taskId);
    if type(config) ~= 'table' then
        trace(PURE_FILE, "任务(%d)不存在，无法完成。", taskId);
        return false;
    end

    local curProgress = getProgress(taskId);
    setProgress(taskId, curProgress + count);

    return true;
end

-- 获取一个任务的进度
function getProgress(taskId)
    local tasks = ME.user.dbase:query("dungeon_tasks", {});
    if type(tasks[taskId]) ~= 'table' then
        -- 尚未领取该任务
        return 0;
    end

    return tasks[taskId]["progress"];
end

-- 设置任务进度
function setProgress(taskId, progress)
    local tasks = ME.user.dbase:query("dungeon_tasks", {});
    if type(tasks[taskId]) ~= 'table' then
        -- 尚未领取该任务
        trace(PURE_FILE, "未领取任务(%d)，无法设置任务进度。", taskId);
        return false;
    end

    -- 控制进度不超过上限
    local requireProgress = query(taskId, "require_progress");
    progress = math.min(progress, requireProgress);

    -- 修改此任务进度
    tasks[taskId]["progress"] = progress;
    ME.user.dbase:set("dungeon_tasks", tasks);

    -- 尝试完成任务
    completeTask(taskId);

    return true;
end

-- 尝试完成任务
function completeTask(taskId)
    if true ~= isCompleted(taskId) then
        return false;
    end

    DungeonLogM.addLog(string.format("[DungeonTaskM]任务(%d)完成", taskId));

    -- 抛出完成任务事件
    EventMgr.fire(event.DUNGEON_TASK_COMPLETE, { ["id"] = taskId, });

    return true;
end

-- 判断一个任务是否已经完成了
function  isCompleted(taskId)
    local tasks =  ME.user.dbase:query("dungeon_tasks", {});
    if type(tasks[taskId]) ~= 'table' then
        -- 尚未领取该任务
        return false;
    end

    local config = query(taskId);
    if type(config) ~= 'table' then
        -- 该任务不存在
        return false;
    end

    local requireProgress = config["require_progress"];
    return tasks[taskId]["progress"] >= requireProgress;
end

-- 领取任务奖励
function takeBonus(taskId)
    if true ~= isCompleted(taskId) then
        trace(PURE_FILE, "尚未完成任务(%d)，无法领取任务奖励。", taskId);
        return false;
    end

    local config = query(taskId);
    if type(config) ~= 'table' then
        -- 该任务不存在
        trace(PURE_FILE, "任务(%d)不存在，无法领取奖励。", taskId);
        return false;
    end

    -- 任务奖励信息
    local bonus = config["bonus"];
    if  type(bonus) == "string" and
        string.startWith(bonus, "formula_") then
        local formula = string.sub(bonus, string.len("formula_") + 1);
        bonus = FormulaM.invoke(formula, taskId);
    end

    if #bonus == 0 then
        error(string.format("尚未配置任务(%d)的奖励。", taskId));
        return false;
    end

    -- 清除任务
    local tasks = ME.user.dbase:query("dungeon_tasks");
    tasks[taskId]["times"] = (tasks[taskId]["times"] or 0) - 1;
    if tasks[taskId]["times"] <= 0 then
        tasks[taskId] = nil;
    end

    -- 执行奖励
    for _, arr in pairs(bonus) do
        BonusM.doBonus(arr, "dungeon_task");
    end

    return true;
end





